﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Globalization;
using System.Reflection;
using System.IO;

using Microsoft.Phone.Controls;

using C1.Phone.Maps;
using C1.Phone;
using Microsoft.Phone.Shell;

namespace ControlExplorer.Controls.Maps
{
    public partial class VectorMap
        : UserControl, IExposeApplicationBarItems 
    {
        ApplicationBarIconButton btnLegend = new ApplicationBarIconButton();
        ApplicationBarIconButton btnZoomOrigin = new ApplicationBarIconButton();
        Countries countries = new Countries();
        C1VectorLayer vl; 

        public VectorMap()
        {
            InitializeComponent();

            btnLegend.IconUri = new Uri("/Resources/AppBar/info.png", UriKind.Relative);
            btnLegend.Text = "legend";
            btnLegend.Click += btnLegend_Click;

            btnZoomOrigin.IconUri = new Uri("/Resources/AppBar/zoom_1-1.png", UriKind.Relative);
            btnZoomOrigin.Text = "zoom out";
            btnZoomOrigin.Click += btnZoomOrigin_Click;

            Loaded += VectorMap_Loaded;
        }

        void btnZoomOrigin_Click(object sender, EventArgs e)
        {
            maps.TargetZoom = 0;
            maps.TargetCenter = new Point();
        }

        void VectorMap_Loaded(object sender, RoutedEventArgs e)
        {
            // create VectorLayer
            vl = new C1VectorLayer()
            {
                LabelVisibility = LabelVisibility.Hidden,
                Foreground = new SolidColorBrush(Color.FromArgb(255, 0x97, 0x35, 0x35))
            };

            // read text data from resources            
            var rs = Application.GetResourceStream(new Uri("/ControlExplorer" + App.AssemblySuffix + ";component/Resources/Maps/gdp-ppp.txt", UriKind.Relative));
            if (rs == null)
                return;

            using (Stream stream = rs.Stream)
            {
                using (StreamReader sr = new StreamReader(stream))
                {
                    for (; !sr.EndOfStream; )
                    {
                        string s = sr.ReadLine();

                        string[] ss = s.Split(new char[] { '\t' },
                          StringSplitOptions.RemoveEmptyEntries);

                        countries.Add(new Country() { Name = ss[1].Trim(), Value = double.Parse(ss[2], CultureInfo.InvariantCulture) });
                    }
                }
            }

            // create palette
            ColorValues cvals = new ColorValues();
            cvals.Add(new ColorValue() { Color = Color.FromArgb(255, 241, 244, 255), Value = 0 });
            cvals.Add(new ColorValue() { Color = Color.FromArgb(255, 241, 244, 255), Value = 5000 });
            cvals.Add(new ColorValue() { Color = Color.FromArgb(255, 224, 224, 246), Value = 10000 });
            cvals.Add(new ColorValue() { Color = Color.FromArgb(255, 203, 205, 255), Value = 20000 });
            cvals.Add(new ColorValue() { Color = Color.FromArgb(255, 179, 182, 230), Value = 50000 });
            cvals.Add(new ColorValue() { Color = Color.FromArgb(255, 156, 160, 240), Value = 100000 });
            cvals.Add(new ColorValue() { Color = Color.FromArgb(255, 127, 132, 243), Value = 200000 });
            cvals.Add(new ColorValue() { Color = Color.FromArgb(255, 89, 97, 230), Value = 500000 });
            cvals.Add(new ColorValue() { Color = Color.FromArgb(255, 56, 64, 217), Value = 1000000 });
            cvals.Add(new ColorValue() { Color = Color.FromArgb(255, 19, 26, 148), Value = 2000000 });
            cvals.Add(new ColorValue() { Color = Color.FromArgb(255, 0, 3, 74), Value = 1.001 * countries.GetMax() });

            countries.Converter = cvals;

            // read world map from resources
            Utils.LoadKMZFromResources(vl, new Uri("ControlExplorer" + App.AssemblySuffix + ";component/Resources/Maps/WorldMap.kmz", UriKind.Relative), true, ProcessWorldMap);

            maps.Layers.Add(vl);

            maps.TargetZoomChanged += maps_TargetZoomChanged;

            InitLegend();            
        }

        void btnLegend_Click(object sender, EventArgs e)
        {
            legendPanel.Visibility = legendPanel.Visibility == Visibility.Collapsed
                ? Visibility.Visible
                : Visibility.Collapsed;
        }

        void maps_TargetZoomChanged(object sender, PropertyChangedEventArgs<double> e)
        {
            if (e.NewValue >= 2)
                vl.LabelVisibility = LabelVisibility.AutoHide;
            else
                vl.LabelVisibility = LabelVisibility.Hidden;
        }

        bool ProcessWorldMap(C1VectorItemBase v)
        {
            string name = v.Tag as string ?? "";

            Country country = countries[name];
            if (country != null)
                v.Fill = country.Fill;
            else
                v.Fill = null;

            return true;
        }

        void InitLegend()
        {
            ColorValues cvals = (ColorValues)countries.Converter;
            var legendItems = new List<LegendItem>();

            for (int i = 0; i < cvals.Count - 1; i++)
            {
                ColorValue cv = cvals[i];

                LinearGradientBrush lgb = new LinearGradientBrush() { StartPoint = new Point(0, 0), EndPoint = new Point(0, 1) };
                lgb.GradientStops.Add(new GradientStop() { Color = cv.Color, Offset = 0 });
                lgb.GradientStops.Add(new GradientStop() { Color = cvals[i + 1].Color, Offset = 1 });

                legendItems.Add(new LegendItem() 
                { 
                    Brush = lgb, 
                    Text =  cv.Value.ToString("N0") 
                });
            }
            legend.ItemsSource = legendItems;
        }


        #region IExposeApplicationBarItems Members

        public IEnumerable<IApplicationBarMenuItem> ApplicationBarItems
        {
            get 
            {
                yield return btnLegend;

                yield return btnZoomOrigin;
            }
        }

        #endregion
    }

    public class LegendItem
    {
        public Brush Brush { get; set; }
        public string Text { get; set; }
    }
}